package com.demo.base;

import com.demo.utils.StringUtils;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 基础Controller类.
 * Created by xiaoyu
 */
public class BaseController {
    Logger LOGGER = LoggerFactory.getLogger(BaseController.class);

    public static String getUserUid(HttpServletRequest request) {
        Object uuid = request.getAttribute("uuid");
        return null != uuid ? uuid.toString() : null;
    }


    protected void putSession(HttpServletRequest request, String key, Object value) {
        request.getSession().setAttribute(key, value);
    }

    protected Object getSession(HttpServletRequest request, String key) {
        return request.getSession().getAttribute(key);
    }

    /**
     * 根据Key获取Request中的参数值
     *
     * @param key Request中的Key值
     * @return 返回与Key值对应的Value值
     */
    protected String getParameter(HttpServletRequest request, String key) {
        String[] results = request.getParameterValues(key);
        if (results == null) {
            return "";
        } else if (results.length == 1) {
            return results[0];
        } else {
            StringBuilder sb = new StringBuilder();
            for (String str : results) {
                if (StringUtils.isNotEmpty(str)) {
                    sb.append(str).append(",");
                }
            }
            String result = sb.toString();
            if (result.endsWith(",")) {
                result = result.substring(0, result.length() - 1);
            }

            return result;
        }
    }

    /**
     * 获取类类型的所有Field包括父类中的Field
     *
     * @param clazz 类类型
     * @return 返回类类型的所有Field包括父类中的Field
     */
    public Field[] getAllFields(Class clazz) {
        Map<String, Field> map = new HashMap<String, Field>();
        for (Field field : clazz.getDeclaredFields()) {
            map.put(field.getName(), field);
        }
        while (clazz.getSuperclass() != null) {
            clazz = clazz.getSuperclass();
            if (clazz == Object.class) {
                break;
            }

            for (Field field : clazz.getDeclaredFields()) {
                if (!map.containsKey(field.getName())) {
                    map.put(field.getName(), field);
                }
            }
        }
        return map.values().toArray(new Field[map.size()]);
    }

    /**
     * 封装表单数据
     *
     * @param modelClass POJO模型
     * @param object     POJO模型实例对象
     * @param value      各表单的值
     * @param fieldName  POJO字段名
     * @param fieldType  字段类型
     * @param <T>
     */
    private <T> void invokeMethod(Class<T> modelClass, T object, String value, String fieldName, Class fieldType) {
        Method method = null;
        try {
            method = modelClass.getMethod("set" + StringUtils.firstCharToUpper(fieldName), fieldType);
        } catch (NoSuchMethodException e) {
            if (fieldType == Boolean.class || fieldType == boolean.class) {
                try {
                    method = modelClass.getMethod("set" + StringUtils.firstCharToUpper(fieldName.startsWith("is") ? fieldName.replace("is", "") : fieldName), fieldType);
                } catch (NoSuchMethodException e1) {
                    LOGGER.warn(e1.getMessage());
                }
            } else {
                LOGGER.warn(e.getMessage());
            }
        }
        try {
            if (null != method) {
                if (fieldType == String.class) {
                    method.invoke(object, value);
                } else if (fieldType == double.class || fieldType == Double.class) {
                    try {
                        method.invoke(object, Double.parseDouble(value));
                    } catch (NumberFormatException e) {
                        e.printStackTrace();
                    }
                } else if (fieldType == int.class || fieldType == Integer.class) {
                    try {
                        method.invoke(object, Integer.parseInt(value));
                    } catch (NumberFormatException e) {
                        e.printStackTrace();
                    }
                } else if (fieldType == Boolean.class || fieldType == boolean.class) {
                    try {
                        method.invoke(object, Boolean.parseBoolean(value));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else if (fieldType == Date.class) {
                    try {
                        SimpleDateFormat sdf = (value.length() == 10 ? new SimpleDateFormat("yyyy-MM-dd") : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
                        method.invoke(object, sdf.parse(value));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取表单实例
     *
     * @param model POJO模型
     * @param <T>   返回的实例
     * @return 表单实体（一般为特定的POJO或者数据库表POJO）
     */
    protected <T> T getModel(HttpServletRequest request, Class<T> model) {
        Field[] fields = getAllFields(model);
        String value;
        Method method;
        T t;
        try {
            t = model.newInstance();
        } catch (Exception e) {
            LOGGER.error("创建模型类实例失败！！！", e);
            throw new RuntimeException(e);
        }

        for (Field field : fields) {
            int modifiers = field.getModifiers();
            if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) {
                continue;
            }
            value = getParameter(request, field.getName());
            if (StringUtils.isEmpty(value)) {
                if (field.getType() == String.class) {
                    try {
                        method = model.getMethod("get" + StringUtils.firstCharToUpper(field.getName()));
                        Object invokeValue = method.invoke(t);
                        if (invokeValue != null) {
                            value = invokeValue.toString();
                        }
                    } catch (Exception e) {
                        if (field.getType() == Boolean.class || field.getType() == boolean.class) {
                            try {
                                String fieldName = field.getName();
                                method = model.getMethod("get" + StringUtils.firstCharToUpper(fieldName.startsWith("is") ? fieldName.replace("is", "") : fieldName));
                                Object invokeValue = method.invoke(t);
                                if (invokeValue != null) {
                                    value = invokeValue.toString();
                                }
                            } catch (Exception e1) {
                                LOGGER.warn(e1.getMessage());
                            }
                        } else {
                            LOGGER.warn(e.getMessage());
                        }
                    }
                }
            }

            LOGGER.debug(field.getName() + " --> " + value);

            if (StringUtils.isNotEmpty(value)) {
                invokeMethod(model, t, value, field.getName(), field.getType());
            }
        }

        return t;
    }

    private void setValue(Class clazz, Object t, String fieldName, String value) {
        Method method;
        try {
            method = clazz.getDeclaredMethod("set" + StringUtils.firstCharToUpper(fieldName), String.class);
            method.invoke(t, value);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    /**
     * <p>Description:获取request里面的参数</p>
     * <p>Author:Gred</p>
     * <p>Date:2017/4/21 19:31</p>
     * <p>param:paramMap</p>
     **/
    protected String checkAuthentication(Map<String, String[]> paramMap) {

        Collection<String> keyset = paramMap.keySet();
        List<String> list = new ArrayList<String>(keyset);
        Collections.sort(list);
        String paramEncodeStr = "";
        for (int i = 0; i < list.size(); i++) {
            String paramKey = list.get(i);
            String paramVal = paramMap.get(list.get(i))[0];
            if (StringUtils.isNotEmpty(paramVal)) {
                paramEncodeStr += list.get(i) + "=" + paramVal + "&";
            }
        }
        return paramEncodeStr;
    }
}
